package org.finmanager.core;

import com.alee.extended.panel.WebButtonGroup;
import com.alee.laf.button.WebButton;
import javax.swing.*;
import javax.swing.table.*;

import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.GregorianCalendar;

import static org.finmanager.core.Constants.DATE_FORMAT;
import static org.finmanager.core.Constants.TABLE_COLUMN_COLOR1;
import static org.finmanager.core.Constants.TABLE_COLUMN_COLOR2;

/**
 * Created by Kelvin on 20/3/2014.
 * <p/>
 * This class mainly contains a table for viewing items
 */
public class ItemManagerUI {
	private JPanel mainPanel = new JPanel();

	private JTable table;

	private JPanel favouritesPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));

	private ArrayList<WebButton> buttons = new ArrayList<WebButton>();

	private ItemPopUpMenu popUpMenu;

	public ItemManagerUI(ItemManagerController itemManagerController) {
		popUpMenu = new ItemPopUpMenu(this);

		table = new JTable(itemManagerController.getItemModel().getItemTableModel());
		JScrollPane scrollPane = new JScrollPane(table);
		scrollPane.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.DARK_GRAY));

		table.setAutoCreateRowSorter(true);

		TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel());
		table.setRowSorter(sorter);

		sorter.setSortable(ItemTableModel.NAME, false);
		sorter.setSortable(ItemTableModel.DATE, false);
		sorter.setSortable(ItemTableModel.AMOUNT, false);
		sorter.setSortable(ItemTableModel.CATEGORY, false);

		ArrayList<RowSorter.SortKey> list = new ArrayList<RowSorter.SortKey>();
		list.add(new RowSorter.SortKey(ItemTableModel.DATE, SortOrder.DESCENDING));
		sorter.setSortKeys(list);
		sorter.sort();


		// The column of "name" is wider
		// The column of "amount" is narrower
		TableColumn column;
		for (int i = 0; i < table.getColumnCount(); ++i) {
			column = table.getColumnModel().getColumn(i);
			if (i == ItemTableModel.NAME)
				column.setPreferredWidth(400);
			else if (i == ItemTableModel.AMOUNT)
				column.setPreferredWidth(70);
			else
				column.setPreferredWidth(100);
		}
		table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);

		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.setColumnSelectionAllowed(false);

		table.getTableHeader().setReorderingAllowed(false);
		table.getTableHeader().setResizingAllowed(false);

		table.setShowGrid(false);
		table.setIntercellSpacing(new Dimension(0,0));

		table.setFillsViewportHeight(true);

		// Custom renderer to remove selection border
		table.setDefaultRenderer(Object.class, new ItemTableRenderer());
		table.setDefaultRenderer(Double.class, new DoubleRenderer());

		// Custom renderer to show dates properly
		table.setDefaultRenderer(GregorianCalendar.class, new DateRenderer());
		table.setComponentPopupMenu(popUpMenu);

		table.addMouseListener(new TableMouseAdapter(table));


		//On top of the table, there are some buttons
		//1. Filter what to see in the table by choosing category
		//2. Choose favourite category
		//3. "+" button to add items
		JPanel topPanel = new JPanel();
		topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.LINE_AXIS));
		JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));

		WebButton selectConstraintButton = new WebButton("Filter");
		WebButton categoryManagerButton = new WebButton("Cat");
		WebButton addItemButton = new WebButton("+");

		selectConstraintButton.setActionCommand(ItemManagerController.OPEN_ITEM_FILTER_UI);
		selectConstraintButton.setDrawFocus(false);
		buttons.add(selectConstraintButton);
		categoryManagerButton.setActionCommand(ItemManagerController.OPEN_CATEGORY_MANAGER);
		categoryManagerButton.setDrawFocus(false);
		buttons.add(categoryManagerButton);
		addItemButton.setActionCommand(ItemManagerController.OPEN_ITEM_INPUT_UI_ADD);
		addItemButton.setDrawFocus(false);
		buttons.add(addItemButton);


		controlPanel.add(new WebButtonGroup(true, selectConstraintButton, categoryManagerButton, addItemButton));

		topPanel.add(favouritesPanel);
		topPanel.add(Box.createHorizontalGlue());
		topPanel.add(controlPanel);

		getMainComponent().setLayout(new BorderLayout(0, 0));
		getMainComponent().add(topPanel, BorderLayout.NORTH);
		getMainComponent().add(scrollPane, BorderLayout.CENTER);
	}

	public void setFilter(RowFilter<CategoryTableModel, Integer> filter) {
		TableRowSorter<CategoryTableModel> sorter = (TableRowSorter) table.getRowSorter();
		sorter.setRowFilter(filter);
	}

	public void addButtonListener(ActionListener listener) {
		for (JButton button : buttons) {
			button.addActionListener(listener);
		}
		popUpMenu.addMenuItemListener(listener);
	}

	public JPanel getFavouritesPanel() {
		return favouritesPanel;
	}

	public int getSelectedRowInModel() {
		return table.convertRowIndexToModel(table.getSelectedRow());
	}

	public JComponent getMainComponent() {
		return mainPanel;
	}

	private class ItemTableRenderer extends DefaultTableCellRenderer {
		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
			setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 5));

			if (isSelected) {
				setBackground(table.getSelectionBackground());
			} else {
				setBackground((row % 2 == 0) ? TABLE_COLUMN_COLOR1 : TABLE_COLUMN_COLOR2);
			}

			return this;
		}
	}

	private class DoubleRenderer extends ItemTableRenderer {
		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
			setHorizontalAlignment(JLabel.RIGHT);
			DecimalFormat df = new DecimalFormat("#.#");
			setText(df.format(value));
			return this;
		}
	}

	// Display date properly by specifying a format to display
	private class DateRenderer extends ItemTableRenderer {
		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

			SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
			GregorianCalendar date = (GregorianCalendar) value;

			setText(dateFormat.format(date.getTime()));

			return this;
		}
	}

	// Selecting the row when a mouse right click on it
	// Need to find the item data when edit/delete
	// The correct data can be found by looking for the selected row
	private class TableMouseAdapter extends MouseAdapter {

		private JTable table;

		public TableMouseAdapter(JTable table) {
			this.table = table;
		}

		@Override
		public void mousePressed(MouseEvent e) {
			if (e.getButton() == MouseEvent.BUTTON3) {
				Point point = e.getPoint();
				int currentRow = table.rowAtPoint(point);
				if (currentRow != -1)
					table.setRowSelectionInterval(currentRow, currentRow);
			}
		}
	}
}
